package com.zjitc.service.imp;

import com.rabbitmq.client.ConnectionFactory;
import com.zjitc.common.Gsonal;
import com.zjitc.common.ServerResponse;
import com.zjitc.common.redis.RedisCache;
import com.zjitc.mapper.*;
import com.zjitc.pojo.*;
import com.zjitc.service.ProductService;
import com.zjitc.utils.old.*;
import com.zjitc.vo.product.FullProduct;
import com.zjitc.vo.PageModel;
import com.zjitc.vo.product.Prestrain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Create By IntelliJ IDEA
 *
 * @author: myq
 * @create-Time: 2017/11/15  10:57
 */
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private CollectMapper collectMapper;
    @Autowired
    private RedisCache redis;
    @Autowired
    private ConnectionFactory factory;
    @Autowired
    private CarMapper carMapper;

    /**
     * 交换机
     */
    private final String EXCHANGE_NAME = "Exchange_BigWork";
    private final String INVENTORY = "inventory";
    private static final String COLLECT = "collect";
    private final String HOTS = "Hots";
    private final String NEWS = "News";
    private final String PRODUCTS = "products";
    private final String CATEGORY = "category";
    //上架中
    private static String PUTAWAY = "1";
    //下架
    private static String SOLDOUT = "0";

    @Override
    public List<Product> findHots() {
        checkredis();
        List<Product> products = redis.hashListGetAll(HOTS, Product.class);
        if (products.size() > MyNumber.TEN.ordinal()) {
            return products.subList(0, 10);
        }
        return products;
    }

    @Override
    public List<Product> findNews() {
        checkredis();
        List<Product> products = redis.hashListGetAll(NEWS, Product.class);
        if (products.size() > MyNumber.TEN.ordinal()) {
            return products.subList(0, 10);
        }
        return products;
    }

    @Override
    public Product findbyid(String pid) {
        Product product = redis.hashgetObject(PRODUCTS, pid, Product.class);
        return product;
    }

    @Override
    public PageModel findallProduct(String cid, int pageid, int count) {
        checkredis();
        List<Product> productList = redis.hashListGetAll(PRODUCTS, Product.class);
        List<Product> products = new ArrayList<>();
        productList.forEach(product -> {
            if (cid.equals(product.getCid())) {
                products.add(product);
            }
        });
        PageModel info = new PageModel(products, count, pageid);
        return info;
    }

    @Override
    public PageModel<Product> findAllProduct(int pageid, int count) {
        checkredis();
        List<Product> products = redis.hashListGetAll(PRODUCTS, Product.class);
        PageModel pageModel = new PageModel(products, count, pageid);
        return pageModel;
    }

    @Override
    public List<Product> findall() {
        return productMapper.findall();
    }


    @Override
    public ModelAndView displaymsg(HttpSession session, String pid) {
        User user = (User) session.getAttribute("user");
        checkredis();
        boolean temp = false;
        if (user != null) {
            checkcollect(user.getUid());
            String ident = user.getUid().substring(0, 10);
            Collect collect = redis.hashgetObject(COLLECT + ident, pid, Collect.class);
            if (collect != null) {
                temp = true;
            }
        }
        ModelAndView mc = new ModelAndView("product/product_info");
        Product product = redis.hashgetObject(PRODUCTS, pid, Product.class);
        mc.addObject("collect", temp);
        mc.addObject("product", product);
        return mc;
    }


    @Override
    public int updateProduct(Product product) {
        int update = productMapper.update(product);
        redis.hashset(PRODUCTS, product.getPid(), Gsonal.tojson(product));
        return update;
    }

    @Override
    public int addproduct(Product product) {
        product.setState(SOLDOUT);
        product.setShelfTime(String.valueOf(new Date()));
        redis.hashset(PRODUCTS, product.getPid(), Gsonal.tojson(product));
        int i = productMapper.addnewProduct(product);
        return i;
    }

    @Override
    //有错误
    public void deleteByPid(String pid) {
        redis.flushDB();
        collectMapper.delCollectbypid(pid);
        carMapper.deletebyPid(pid);
        orderMapper.deleteorderitembypid(pid);
        int i = productMapper.deletebypid(pid);
        updateRedis();
    }


    @Override
    public int updateInventory(String pid, Integer count) {
        Product product = redis.hashgetObject(PRODUCTS, pid, Product.class);
        product.setStock(count);
        redis.hashset(PRODUCTS, pid, Gsonal.tojson(product));
        return productMapper.update(product);
    }

    @Override
    public ServerResponse updateCollect(String pid, User user) {
        checkcollect(user.getUid());
        String ident = user.getUid().substring(0, 10);
        Collect collect = redis.hashgetObject(COLLECT + ident, pid, Collect.class);
        Boolean b = true;
        if (collect == null) {
            b = false;
            collect = new Collect(user.getUid(), pid);
        }
        int temp = 0;

        if (!b) {
            redis.hashset(COLLECT + ident, pid, Gsonal.tojson(collect));
            collectMapper.addcollect(collect);
            temp = 1;
        } else {
            redis.delHash(COLLECT + ident, pid);
            collectMapper.delCollect(collect);
        }
        return ServerResponse.createSuccess(temp);
    }

    //  新加
    @Override
    public List<Prestrain> prestrainProduct() {
        List<Prestrain> products = new ArrayList<>();
        List<Category> list = categoryMapper.findAll();
        list.forEach(c -> {
            List<Product> productList = redis.hashListGetAll(CATEGORY + c.getCid(), Product.class);
            if (productList.size() >= 5) {
                productList.subList(0, 5);
                products.add(new Prestrain(c, productList));
            }
        });
        return products;
    }

    @Override
    public List<Product> findMyCollect(String uid) {
        List<Product> products = new ArrayList<>();
        checkcollect(uid);
        String ident = uid.substring(0, 10);
        List<Collect> collects = redis.hashListGetAll(COLLECT + ident, Collect.class);
        collects.forEach(collect -> {
            Product product = redis.hashgetObject(PRODUCTS, collect.getPid(), Product.class);
            products.add(product);
        });
        return products;
    }

    @Override
    public ModelAndView initProductList(String cid, Integer pageid, HttpSession session, int count) {
        User user = (User) session.getAttribute("user");
        if (user == null) {
            return NoUserInit(cid, pageid, count);
        } else {
            return UserInit(cid, pageid, count, user.getUid());
        }
    }

    @Override
    public ModelAndView initFuzzyList(String fuzzy, HttpSession session, int pageid, int count) {
        User user = (User) session.getAttribute("user");
        if (user == null) {
            return NoUserFuzzy(fuzzy, pageid, count);
        } else {
            return UserFuzzy(fuzzy, pageid, count, user.getUid());
        }
    }

    @Override
    public int findcount() {
        return redis.hashListGetAll(PRODUCTS, Product.class).size();
    }

    @Override
    public String updateState(String pid) {
        Product product = redis.hashgetObject(PRODUCTS, pid, Product.class);
        String state = product.getState();
        if (PUTAWAY.equals(state)) {
            product.setState(SOLDOUT);
        } else {
            product.setState(PUTAWAY);
        }
        redis.hashset(PRODUCTS, pid, Gsonal.tojson(product));
        int update = productMapper.update(product);
        return state;
    }

    @Override
    public List<Product> FuzzyProduct(String name) {
        List<Product> listGetAll = redis.hashListGetAll(PRODUCTS, Product.class);
        List<Product> products = new ArrayList<>();
        Pattern pattern = Pattern.compile(name, Pattern.CASE_INSENSITIVE);
        listGetAll.forEach(item -> {
            Matcher matcher = pattern.matcher(item.getName());
            if (matcher.find()) {
                products.add(item);
            }
        });
        return products;
    }

    @Override
    public List<Product> changeCategory(String cid) {
        List<Product> products = new ArrayList<>();
        List<Product> listGetAll = redis.hashListGetAll(PRODUCTS, Product.class);
        listGetAll.forEach(product -> {
            if (cid.equals(product.getCid())) {
                products.add(product);
            }
        });
        return products;
    }

    @Override
    public Integer[] initAdminMain() {
        final Integer[] week = {0, 0, 0, 0};
        List<Integer> list = new ArrayList<Integer>();
        List<Product> Allproduct = findall();
        week[0] = Allproduct.size();
        long time = System.currentTimeMillis();

        Allproduct.forEach(product -> {
            try {
                long productTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(product.getShelfTime()).getTime();
                if ((time - productTime) / (1000 * 3600 * 24) < 7) {
                    week[1]++;
                }
                if ((time - productTime) / (1000 * 3600 * 24) < 30) {
                    week[2]++;
                }else{
                    week[3]++;
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });
        return week;
    }

    //_--------------_____________----------------------________________---------------------------
    private ModelAndView UserFuzzy(String fuzzy, int pageid, int count, String uid) {
        ModelAndView mv = new ModelAndView("product/product_list");
        checkcollect(uid);
        List<Product> products = findHots();
        List<Product> collects = findMyCollect(uid);
        List<FullProduct> fuzzysearch = fuzzysearch(fuzzy);
        fuzzysearch = InitCollect(collects, fuzzysearch);
        PageModel pageModel = InitPageModel(fuzzysearch, count, pageid);
        mv.addObject("pagemodel", pageModel);
        mv.addObject("hots", products);
        mv.addObject("collect", collects);
        return mv;
    }

    private ModelAndView NoUserFuzzy(String fuzzy, int pageid, int count) {
        ModelAndView mv = new ModelAndView("product/product_list");
        List<Product> hots = findHots();
        List<FullProduct> fuzzysearch = fuzzysearch(fuzzy);
        PageModel pageModel = InitPageModel(fuzzysearch, count, pageid);
        mv.addObject("hots", hots);
        mv.addObject("pagemodel", pageModel);
        return mv;
    }

    private ModelAndView UserInit(String cid, Integer pageid, int count, String uid) {
        ModelAndView mv = new ModelAndView("product/product_list");
        checkcollect(uid);
        List<Product> products = findHots();
        List<Product> collects = findMyCollect(uid);
        mv.addObject("hots", products);
        mv.addObject("collect", collects);
        if ("".equals(cid)) {
            List<FullProduct> fullProducts = findFullProduct();
            fullProducts = InitCollect(collects, fullProducts);
            PageModel info = InitPageModel(fullProducts, count, pageid);
            mv.addObject("pagemodel", info);
            mv.addObject("cid", "");
        } else {
            List<FullProduct> fullProducts = findfullProduct(cid);
            fullProducts = InitCollect(collects, fullProducts);
            PageModel info = InitPageModel(fullProducts, count, pageid);
            mv.addObject("pagemodel", info);
            mv.addObject("cid", cid);
        }
        return mv;
    }

    private ModelAndView NoUserInit(String cid, Integer pageid, int count) {
        ModelAndView mv = new ModelAndView("product/product_list");
        List<Product> products = findHots();
        mv.addObject("hots", products);
        if ("".equals(cid)) {
            List<FullProduct> fullProducts = findFullProduct();
            PageModel info = InitPageModel(fullProducts, count, pageid);
            mv.addObject("pagemodel", info);
        } else {
            List<FullProduct> fullProducts = findfullProduct(cid);
            PageModel info = InitPageModel(fullProducts, count, pageid);
            mv.addObject("pagemodel", info);
            mv.addObject("cid", cid);
        }
        return mv;
    }


    /**
     * 模糊查询
     *
     * @param fuzzy
     * @return
     */
    private List<FullProduct> fuzzysearch(String fuzzy) {
        List<Product> listGetAll = redis.hashListGetAll(PRODUCTS, Product.class);
        List<FullProduct> results = new ArrayList();
        Pattern pattern = Pattern.compile(fuzzy, Pattern.CASE_INSENSITIVE);
        listGetAll.forEach(item -> {
            Matcher matcher = pattern.matcher(item.getName());
            if (matcher.find()) {
                results.add(new FullProduct(item));
            }
        });
        return results;
    }

    /**
     * cid 为空的查找
     *
     * @return
     */
    private List<FullProduct> findFullProduct() {
        checkredis();
        List<FullProduct> fullProducts = new ArrayList<>();
        List<Product> products = redis.hashListGetAll(PRODUCTS, Product.class);
        products.forEach(product -> {
            FullProduct fullPro = new FullProduct(product);
            fullProducts.add(fullPro);
        });
        return fullProducts;
    }

    /**
     * cid不为空的查找
     *
     * @param cid
     * @return
     */
    private List<FullProduct> findfullProduct(String cid) {
        checkredis();
        List<FullProduct> fullProducts = new ArrayList<>();
        List<Product> products = redis.hashListGetAll(PRODUCTS, Product.class);
        products.forEach(product -> {
            if (cid.equals(product.getCid())) {
                FullProduct fullpro = new FullProduct(product);
                fullProducts.add(fullpro);
            }
        });
        return fullProducts;
    }

    /**
     * 对fullproduct对象进行配比
     *
     * @param collects
     * @param fullProducts
     * @return
     */
    private List<FullProduct> InitCollect(List<Product> collects, List<FullProduct> fullProducts) {
        collects.forEach(collect -> {
            fullProducts.forEach(fullProduct -> {
                if (collect.getPid().equals(fullProduct.getPid())) {
                    fullProduct.setCollect(true);
                    return;
                }
            });
        });
        return fullProducts;
    }

    /**
     * 令其返回为 pagemodel
     *
     * @return
     */
    private PageModel InitPageModel(List<FullProduct> fullProducts, int count, Integer pageid) {
        return new PageModel(fullProducts, count, pageid);
    }

    private void checkcollect(String uid) {
        String ident = uid.substring(0, 10);
        if (!redis.exists(COLLECT)) {
            RedisAuto.collectRedis(collectMapper, redis, uid, COLLECT + ident);
        }
    }

    private void makeHistory(HttpSession session, Product product) {
        Object o = session.getAttribute("history");
        History history = null;
        if (o == null) {
            history = new History();
            session.setAttribute("history", history);
        } else {
            history = (History) o;
        }
        history.add(product);
    }

    private void checkredis() {
        if (!redis.exists(PRODUCTS)) {
            RedisAuto.productRedis(productMapper, categoryMapper, redis, PRODUCTS);
        }
        if (!redis.exists(HOTS)) {
            RedisAuto.hotsRedis(productMapper, redis, HOTS);
        }
        if (!redis.exists(NEWS)) {
            RedisAuto.newsRedis(productMapper, redis, NEWS);
        }
//    库存
        RedisAuto.inventoryRedis(productMapper, redis, INVENTORY);
    }

    private void updateRedis() {
        RedisAuto.productRedis(productMapper, categoryMapper, redis, PRODUCTS);
        RedisAuto.hotsRedis(productMapper, redis, HOTS);
        RedisAuto.newsRedis(productMapper, redis, NEWS);
        RedisAuto.inventoryRedis(productMapper, redis, INVENTORY);
    }
}
